<?php

if (!function_exists('ip')) {
    /**
     * 获取客户端IP
     *
     * @return string
     */
    function ip()
    {
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
        if (!empty($_SERVER['REMOTE_ADDR'])) {
            return $_SERVER['REMOTE_ADDR'];
        }
        return '';
    }
}


if (!function_exists('sslDecode')) {
    /**
     * 解密
     *
     * @param string $ciphertext 要解密的数据
     * @param string $key        密钥
     * @param string $cipher     解密方式
     *
     * @return mixed|null
     */
    function sslDecode(string $ciphertext, $key = '2i5AnEd_8fINhaS5', $cipher = 'AES-128-CBC')
    {
        try {
            $c = base64_decode($ciphertext);
            $ivlen = openssl_cipher_iv_length($cipher);
            $iv = substr($c, 0, $ivlen);
            $hmac = substr($c, $ivlen, $sha2len = 32);
            $ciphertext_raw = substr($c, $ivlen + $sha2len);
            $original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, OPENSSL_RAW_DATA, $iv);
            $calcmac = hash_hmac('sha256', $ciphertext_raw, $key, true);
            if (hash_equals($hmac, $calcmac))//PHP 5.6+ timing attack safe comparison
            {
                return @unserialize($original_plaintext);
            }
        } catch (Exception $exception) {
            return null;
        }
        return null;
    }
}


if (!function_exists('sslEncode')) {
    /**
     * 加密
     *
     * @param        $data   要加密的数据
     * @param string $key    密钥
     * @param string $cipher 加密方式
     *
     * @return string
     */
    function sslEncode($data, $key = '2i5AnEd_8fINhaS5', $cipher = 'AES-128-CBC')
    {
        /*加密*/
        $plaintext = serialize($data);
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_RAW_DATA, $iv);
        $hmac = hash_hmac('sha256', $ciphertext_raw, $key, true);
        return base64_encode($iv . $hmac . $ciphertext_raw);
    }
}


/**
 * 日志信息写入 json格式日志
 *
 * @param array  $arr    要写入的日志内容
 * @param string $file   日志文件名
 * @param bool   $append 是否始终写入同一个文件
 */
function log_arr(array $arr = [], $file = 'history', $append = false)
{
    if (empty($arr)) {
        return null;
    }
    umask(002);
    /*回溯跟踪*/
    $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
    $time = date('Y-m-d H:i:s');
    $class = isset($backtrace[1]['class']) ? $backtrace[1]['class'] : '';
    $type = isset($backtrace[1]['type']) ? $backtrace[1]['type'] : '';
    $fun = isset($backtrace[1]['function']) ? $backtrace[1]['function'] : '';
    $traceId = request()->header('X-Trace-Id', '-');
    $ms = '-';
    if (PHP_SAPI !== 'cli') {
        /*请求处理时间计算*/
        $ms = sprintf('%.2f', (microtime(true) - LARAVEL_START) * 1000);
        $ms = $ms > 1000 ? sprintf('%.2fs', $ms / 1000) : $ms . 'ms';
    } else {
        if ($traceId === '-' && property_exists('\App\Http\Library\Queue', 'microtime') && !empty(\App\Http\Library\Queue::$microtime)) {
            $ms = sprintf('%.2f', (microtime(true) - \App\Http\Library\Queue::$microtime) * 1000);
            $ms = $ms > 1000 ? sprintf('%.2fs', $ms / 1000) : $ms . 'ms';
            $traceId = \App\Http\Library\Queue::$traceId;
        }
    }
    //$exp = "\x20\x08\x00\x20";
    $exp = "\x20";
    $str = sprintf("%s{$exp}[%s]{$exp}[%s]{$exp}[%s::%s::%s]", "[{$time}]", $traceId, $ms, "{$backtrace[0]['file']}", "{$class}{$type}{$fun}", "{$backtrace[0]['line']}");

    /*日志正文*/
    foreach ($arr as $k => $v) {
        $k = is_string($k) ? "{$exp}{$k}:" : $exp;
        if (is_array($v) || is_object($v)) {
            $str .= $k . json_encode($v, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            continue;
        }
        $v = str_replace(["\n", "\r"], '', $v);
        $str .= $k . $v;
    }
    unset($arr);
    /*日志保存地址*/
    if ($append === true) {
        $file = "{$file}.log";
    } else {
        $file = date('Ymd') . "_{$file}.log";
    }
    $path = storage_path() . '/logs/' . date('Ym');
    mkdirs($path);
    return file_put_contents("{$path}/{$file}", $str . PHP_EOL, FILE_APPEND);
}


/**
 * 目录递归创建
 *
 * @param $path
 *
 * @return bool
 */
function mkdirs($path)
{
    if (is_dir($path)) {  //已经是目录了就不用创建
        return true;
    }
    if (is_dir(dirname($path))) {     //父目录已经存在，直接创建
        return mkdir($path, 0777);
    }
    mkdirs(dirname($path));     //从子目录往上创建
    return mkdir($path, 0777);    //因为有父目录，所以可以创建路径
}
/**
 * 判断是否为空
 *
 * @param        string   要判断的字符串
 *
 * @return string
 */
if (!function_exists('isEmpty')) {
    function isEmpty($string)
    {
        if(!isset($string) || is_null($string) || empty($string)){
            return true;
        }else{
            return false;
        }
    }
}
if (!function_exists('dateFrom')) {
    /**
     * 一日之初
     *
     * @param $date
     *
     * @return string
     */
    function dateFrom($date)
    {
        $tab = explode(' ', $date);
        if (!isset($tab[1]))
            $date .= ' ' . implode(':', array(0, 0, 0));

        return $date;
    }
}
if (!function_exists('dateTo')) {
    /**
     * 一日之终
     *
     * @param $date
     *
     * @return string
     */
    function dateTo($date)
    {
        $tab = explode(' ', $date);
        if (!isset($tab[1]))
            $date .= ' ' . implode(':', array(23, 59, 59));

        return $date;
    }
}
/**
 * fun.php
 *
 * 说明:
 *
 * 修改历史
 * ----------------------------------------
 * 2020/5/19 18:35:00   操作:创建
 **/
